﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Reflection;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace DotNetAgent.Core
{
	[Serializable]
	[DataContract]
    public class AgentMessage 
	{
		protected string i_ID;
		[DataMember]
		public string ID
        {
            get { return i_ID; }
            set { i_ID = value; }
        }

		protected string i_MessageType;
		[DataMember]
		public string MessageType
        {
            get { return i_MessageType; }
            set { i_MessageType = value; }
        }

		protected DateTime i_Created = DateTime.Now;
		[DataMember]
		public DateTime Created
        {
            get { return i_Created; }
            set { i_Created = value; }
        }

		protected string i_Sender;
		[DataMember]
		public string Sender
        {
            get { return i_Sender; }
            set { i_Sender = value; }
        }

		//protected string m_from_address;
		//[DataMember]
		//public string FromAddress
		//{
		//    get { return m_from_address; }
		//    set { m_from_address = value; }
		//}

		protected string i_Recipient;
		[DataMember]
		public string Recipient
        {
            get { return i_Recipient; }
            set { i_Recipient = value; }
        }

		//protected string m_to_address;
		//[DataMember]
		//public string ToAddress
		//{
		//    get { return m_to_address; }
		//    set { m_to_address = value; }
		//}

		protected object i_body;
		[DataMember]
		public object Body
        {
            get { return i_body; }
            set { i_body = value; }
        }

		public AgentMessage(String p_Sender, String p_Recipient, String p_MessageType, Object p_Body)
		{
			Sender = p_Sender;
			Recipient = p_Recipient;
			MessageType = p_MessageType;
			Body = p_Body;
		}

		//public AgentMessage(XmlNode node)
		//{
		//    PropertyInfo[] pi = this.GetType().GetProperties();
		//    foreach (PropertyInfo pr in pi)
		//    {
		//        if (node.Attributes[pr.Name] != null)
		//        {
		//            try
		//            {
		//                pr.SetValue(this, node.Attributes[pr.Name].Value, null);
		//            }
		//            catch (Exception ex)
		//            {
		//                throw new AgentException("XML node is not compatible", ex);
		//            }
		//        }
                
		//    }
		//}
        
		public override string ToString()
		{
			return ToXML();
		}

		public string ToXML()
		{
			StringBuilder Str = new StringBuilder();
			Str.Append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
			Str.Append("<msg ");
			Str.Append("ID=\"" + ID + "\" ");
			Str.Append("Type=\"" + MessageType + "\" ");
			Str.Append("Created=\"" + ((Created == DateTime.MinValue) ? "" : Created.ToString("yyyy-MM-dd hh:mm:ss")) + "\" ");
			Str.Append("Sender=\"" + Sender + "\" ");
			Str.Append("Recipient=\"" + Recipient + "\" ");
			Str.Append(">");
			Str.Append(Body);
			Str.Append("</msg>");
			return Str.ToString();
		}

		//public static AgentMessage ReadMsg(XmlNode node)
		//{
		//    AgentMessage Msg = new AgentMessage();
		//    try
		//    {
		//        if (node.Attributes["ID"] != null)
		//        {
		//            Msg.ID = node.Attributes["ID"].Value;
		//        }
				
		//        if (node.Attributes["Type"] != null)
		//        {
		//            Msg.Type = node.Attributes["Type"].Value;
		//        }
								
		//        if (node.Attributes["Created"] != null)
		//        {
		//            DateTime dt;
		//            if (!DateTime.TryParse(node.Attributes["Created"].Value, out dt))
		//            {
		//                throw new AgentException("Created Date not Valid");
		//            }
		//            Msg.Created = dt;
		//        }
				
		//        if (node.Attributes["FromAgent"] != null)
		//        {
		//            Msg.FromAgent = node.Attributes["FromAgent"].Value;
		//        }

		//        if (node.Attributes["FromAddress"] != null)
		//        {
		//            Msg.FromAddress = node.Attributes["FromAddress"].Value;
		//        }

		//        if (node.Attributes["ToAgent"] != null)
		//        {
		//            Msg.ToAgent = node.Attributes["ToAgent"].Value;
		//        }

		//        if (node.Attributes["ToAddress"] != null)
		//        {
		//            Msg.ToAddress = node.Attributes["ToAddress"].Value;
		//        }

		//        Msg.Body = node.Value;
		//        return Msg;
		//    }
		//    catch (Exception ex)
		//    {
		//        throw new AgentException("ReadMsg", "Could not Parse Agent Message (Node: " + node.Value + ")", ex);
		//    }
		//}

		//public static List<AgentMessage> LoadMsgsFromFile(string MsgsFileName, string ToAgentFilter)
		//{
		//    List<AgentMessage> MsgList;
		//    try
		//    {
		//        List<AgentMessage> Msgs = new List<AgentMessage>();
		//        AgentMessage Msg = null;
		//        XmlDocument doc = new XmlDocument();
		//        XmlNodeList nodelist = null;
		//        doc.Load(MsgsFileName);
		//        string MsgsXPath = "msg[@ToAgent='" + ToAgentFilter + "']";
		//        nodelist = doc.DocumentElement.SelectNodes(MsgsXPath);
		//        foreach (XmlNode node in nodelist)
		//        {
		//            Msg = ReadMsg(node);
		//            Msgs.Add(Msg);
		//        }
		//        MsgList = Msgs;
		//    }
		//    catch (Exception ex)
		//    {
		//        throw new AgentException("LoadMsgsFromFile", "Error While Loading Messages", ex);
		//    }
		//    return MsgList;
		//}

		//protected static void SaveMsg(AgentMessage Msg)
		//{
		//    try
		//    {
		//        throw new NotImplementedException();
		//    }
		//    catch (Exception Ex)
		//    {
		//        throw new AgentException("Error Saving Agent Message (Msg: " + Msg.ToXML() + ")(Error: " + Ex.Message + ")", Ex);
		//    }
		//}

        public static Byte[] Serialize(object p_Msg)
        {
            try {
                Byte[] ar;
                using (MemoryStream ms = new MemoryStream())
                {
                    BinaryFormatter bf = new BinaryFormatter();
                    bf.Serialize(ms, p_Msg);
                    ar = ms.ToArray();
                    ms.Close();
                }
                return ar;
            } catch (Exception e) {
                throw new AgentException(String.Format("Message serialization failed. Reason: {0}\n" +
                    "Details in the inner exception.", e.Message), e);
            }
        }

        public static object Deserialize(Byte[] par_byte_array)
        {
            try
            {
                object o;
                using (MemoryStream ms = new MemoryStream())
                {
                    try {
                        BinaryFormatter bf = new BinaryFormatter();
                        ms.Read(par_byte_array, 0, par_byte_array.Length);
                        o = (AgentMessage)bf.Deserialize(ms);
                    } finally {
                        ms.Close();
                    }
                }
                return o;
            }
            catch (Exception e)
            {
                throw new AgentException(String.Format("Message serialization failed. Reason: {0}\n" +
                    "Details in the inner exception.", e.Message), e);
            }
        }

	}
}